package com.chucang.shucang.pms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.chucang.shucang.common.base.constant.CommonConstant;
import com.chucang.shucang.common.base.constant.SecurityConstant;
import com.chucang.shucang.common.base.exception.FastException;
import com.chucang.shucang.common.base.page.PageData;
import com.chucang.shucang.common.base.page.PageQuery;
import com.chucang.shucang.common.base.redis.RedisUtil;
import com.chucang.shucang.common.base.service.impl.CrudServiceImpl;
import com.chucang.shucang.common.base.utils.OpsUtil;
import com.chucang.shucang.common.base.utils.R;
import com.chucang.shucang.pms.constant.PmsCacheConstant;
import com.chucang.shucang.pms.constant.PmsCommonConstant;
import com.chucang.shucang.pms.dao.CollectionMallDao;
import com.chucang.shucang.pms.dto.CollectionMallDTO;
import com.chucang.shucang.pms.entity.CollectionBaseEntity;
import com.chucang.shucang.pms.entity.CollectionMallEntity;
import com.chucang.shucang.pms.feign.UserService;
import com.chucang.shucang.pms.feign.vo.UserBaseEntity;
import com.chucang.shucang.pms.feign.vo.UserCollectionHoldEntity;
import com.chucang.shucang.pms.service.CollectionBaseService;
import com.chucang.shucang.pms.service.CollectionMallService;
import com.chucang.shucang.pms.vo.CollectionBaseOnSaleResVO;
import com.chucang.shucang.pms.vo.CollectionOnSaleDetailResVO;
import com.chucang.shucang.pms.vo.CollectionOnSalePageResVO;
import com.chucang.shucang.pms.vo.CollectionOnSaleResVO;
import com.chucang.shucang.pms.vo.query.CollectionOnSaleQuery;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 藏品商城表
 *
 * @author flitsneak flitsneak@gmail.com
 * @since 1.0.0 2022-09-12
 */
@Service
@RequiredArgsConstructor
public class CollectionMallServiceImpl extends CrudServiceImpl<CollectionMallDao, CollectionMallEntity, CollectionMallDTO> implements CollectionMallService {

    private final CollectionBaseService collectionBaseService;
    private final UserService userService;
    private final RedisUtil redisUtil;

    @Override
    @Cacheable(value = "collectionMallInfo", key = "#id")
    public CollectionMallEntity getTheBottomPrice(Long id) {
        LambdaQueryWrapper<CollectionMallEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(CollectionMallEntity::getCollectionId, id)
                .ne(CollectionMallEntity::getStatus, PmsCommonConstant.COLLECTION_CONSIGN)
                .orderByAsc(CollectionMallEntity::getSellingPrice)
                .select(CollectionMallEntity::getCollectionId, CollectionMallEntity::getSellingPrice)
                .last("limit 1");
        return this.getOne(lambdaQueryWrapper);
    }

    @Override
    public CollectionOnSalePageResVO onSaleCollectionPage(CollectionOnSaleQuery collectionOnSaleQuery) {
        CollectionBaseEntity collectionBase = this.cacheCollectionBaseInfo(collectionOnSaleQuery.getId());

        CollectionBaseOnSaleResVO baseOnSaleResVO = new CollectionBaseOnSaleResVO();
        BeanUtil.copyProperties(collectionBase, baseOnSaleResVO);
        Integer totalNum = baseOnSaleResVO.getTotalNum();
        String dcName = baseOnSaleResVO.getDcName();

        //分页在售商品信息
        LambdaQueryWrapper<CollectionMallEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(CollectionMallEntity::getCollectionId, collectionOnSaleQuery.getId())
                .eq(CollectionMallEntity::getStatus, PmsCommonConstant.COLLECTION_CONSIGN)
                .or()
                .eq(CollectionMallEntity::getStatus, PmsCommonConstant.COLLECTION_LOCKED);
        if (CharSequenceUtil.isBlank(collectionOnSaleQuery.getOrderField())) {
            queryWrapper.orderByAsc(CollectionMallEntity::getSellingPrice);
        } else {
            //设置默认条件以及兜底 阻止恶意构造请求
            this.constructSql(collectionOnSaleQuery, queryWrapper);
        }

        IPage<CollectionMallEntity> page = this.page(
                new PageQuery<CollectionMallEntity>().getPage(collectionOnSaleQuery),
                queryWrapper
        );
        if (CollUtil.isEmpty(page.getRecords())) {
            CollectionOnSalePageResVO collectionOnSalePageResVO = new CollectionOnSalePageResVO();
            collectionOnSalePageResVO.setCollectionBaseOnSaleResVO(baseOnSaleResVO);
            collectionOnSalePageResVO.setPageData(new PageData<>(Collections.emptyList(), 0));
            return collectionOnSalePageResVO;
        }
        List<CollectionOnSaleResVO> collectionOnSaleResVOS = BeanUtil.copyToList(page.getRecords(), CollectionOnSaleResVO.class);
        collectionOnSaleResVOS.forEach(c -> {
            c.setCollectionSerialNum(String.format(CommonConstant.SERIAL_NUM, c.getSerialNum(), totalNum));
            c.setCollectionName(String.format(CommonConstant.PRODUCT_NAME, dcName, c.getSerialNum()));
        });
        PageData<CollectionOnSaleResVO> collectionOnSaleResVOData = new PageData<>(collectionOnSaleResVOS, page.getTotal());
        CollectionOnSalePageResVO collectionOnSalePageResVO = new CollectionOnSalePageResVO();
        collectionOnSalePageResVO.setCollectionBaseOnSaleResVO(baseOnSaleResVO);
        collectionOnSalePageResVO.setPageData(collectionOnSaleResVOData);
        return collectionOnSalePageResVO;
    }

    @Override
    public CollectionOnSaleDetailResVO getOnSaleCollectionDetail(Long id) {
        //在售信息
        CollectionMallEntity byId = this.getById(id);
        //基础信息
        CollectionBaseEntity collectionBase = this.cacheCollectionBaseInfo(byId.getCollectionId());

        CollectionOnSaleDetailResVO collectionOnSaleDetailResVO = new CollectionOnSaleDetailResVO();
        BeanUtil.copyProperties(collectionBase, collectionOnSaleDetailResVO);
        collectionOnSaleDetailResVO.setCollectionName(String.format(CommonConstant.PRODUCT_NAME, collectionBase.getDcName(), byId.getSerialNum()));
        collectionOnSaleDetailResVO.setCollectionSerialNum(String.format(CommonConstant.SERIAL_NUM, byId.getSerialNum(), collectionBase.getTotalNum()));

        collectionOnSaleDetailResVO.setStatus(byId.getStatus());
        collectionOnSaleDetailResVO.setSellerId(byId.getSellerId());
        collectionOnSaleDetailResVO.setSerialNum(byId.getSerialNum());
        collectionOnSaleDetailResVO.setSellingPrice(byId.getSellingPrice());

        //账号信息
        R<UserBaseEntity> baseInfoById = userService.getUserBaseInfoById(byId.getSellerId(), SecurityConstant.FROM_IN);
        UserBaseEntity userBaseEntity = OpsUtil
                .of(baseInfoById)
                .assertDataNotNull(e -> new FastException("获取用户信息失败"))
                .getData()
                .get();

        collectionOnSaleDetailResVO.setUsername(userBaseEntity.getUsername());
        collectionOnSaleDetailResVO.setOffshoreAccount(userBaseEntity.getOffshoreAccount());
        collectionOnSaleDetailResVO.setAccountType(userBaseEntity.getAccountType());

        return collectionOnSaleDetailResVO;
    }

    @Override
    public boolean collectionsOnConsign(List<UserCollectionHoldEntity> userCollectionHoldList) {
        List<CollectionMallEntity> list = new ArrayList<>(16);
        userCollectionHoldList.forEach(c -> {
            CollectionMallEntity mallEntity = new CollectionMallEntity();
            if (Objects.nonNull(c.getConsignId())) {
                mallEntity.setId(c.getConsignId());
            }
            mallEntity.setCollectionId(c.getCollectionId());
            mallEntity.setSellerId(c.getUserId());
            mallEntity.setSerialNum(c.getSerialNum());
            mallEntity.setSellingPrice(c.getSellingPrice());
            mallEntity.setPurchasePrice(c.getPurchasePrice());
            mallEntity.setStatus(PmsCommonConstant.COLLECTION_CONSIGN);
            list.add(mallEntity);
        });
        //TODO 记录日志
        return this.saveOrUpdateBatch(list, 50);
    }

    private CollectionBaseEntity cacheCollectionBaseInfo(Long collectionId) {
        CollectionBaseEntity collectionBase;
        if (Objects.nonNull(redisUtil.getObject(String.format(PmsCacheConstant.COLLECTION_BASE, collectionId)))) {
            collectionBase = (CollectionBaseEntity) redisUtil.getObject(String.format(PmsCacheConstant.COLLECTION_BASE, collectionId));
        } else {
            //获取商品基础信息
            collectionBase = collectionBaseService.getById(collectionId);
            redisUtil.setValue(String.format(PmsCacheConstant.COLLECTION_BASE, collectionId), collectionBase, 12, TimeUnit.HOURS);
        }
        return collectionBase;
    }

    private void constructSql(CollectionOnSaleQuery collectionOnSaleQuery, LambdaQueryWrapper<CollectionMallEntity> queryWrapper) {
        if (collectionOnSaleQuery.getOrderField().equals("sellingPrice")) {
            if (collectionOnSaleQuery.getOrder().equals(CommonConstant.ASC)) {
                queryWrapper.orderByAsc(CollectionMallEntity::getSellingPrice);
            } else {
                queryWrapper.orderByDesc(CollectionMallEntity::getSellingPrice);
            }
        } else if (collectionOnSaleQuery.getOrderField().equals("serialNum")) {
            if (collectionOnSaleQuery.getOrder().equals(CommonConstant.ASC)) {
                queryWrapper.orderByAsc(CollectionMallEntity::getSerialNum);
            } else {
                queryWrapper.orderByDesc(CollectionMallEntity::getSerialNum);
            }
        } else {
            queryWrapper.orderByAsc(CollectionMallEntity::getSellingPrice);
        }
        collectionOnSaleQuery.setOrderField(null);
    }
}